package wxdb.storage;
import wxdb.ui.Global;

import java.util.*;

public class Buffer {
	
	private int pageCount = 0;
	private int cleanCount = 0;
	private ReferCheck rc = new ReferCheck(this);
	HashMap<String,Page> pageHash = new HashMap<String,Page>(Global.STORAGE_BUFFER_SIZE);
	ArrayList<Page> cleanList = new ArrayList<Page>(Global.STORAGE_CLEAN_COUNT);
	
	public Buffer(){
		System.out.println("Buffer :"+Global.STORAGE_BUFFER_SIZE);
		rc.start();
	}
	
	public void addPage(Page pg){
		if(pageCount>=Global.STORAGE_BUFFER_SIZE){
			//add some codes   
			int ref = 0;
			boolean first = true;
			Page rmpg = null;
			for (Iterator<String> iter = pageHash.keySet().iterator(); iter.hasNext();) {  
			    String key = iter.next();  	  
			    Page vapg = pageHash.get(key);
			    if(first){
			    	ref = vapg.getRefer();
			    	rmpg = vapg;
			    	if(vapg.bePined()==false)
			    		first = false;
			    }else{
			    	if(vapg.getRefer()<ref && (vapg.bePined()==false)){
			    		if(vapg.getDataBaseID()==pg.getDataBaseID() && 
			    				(pg.getPageID()-vapg.getPageID()<Global.STORAGE_PREREAD_PAGE))
			    			continue;
			    		rmpg = vapg;
			    		ref = vapg.getRefer();
			    	}
			    }
			}
			removePage(rmpg.getDataBaseID()+";"+rmpg.getPageID());
		}
		//add some codes for add page to buffer
		String key = pg.getDataBaseID() +";"+ pg.getPageID();
		pageHash.put(key, pg);

		pageCount++;
	}
	
	public void removePage(String key){
		String dbid = "";
		String pgid = "";
		int index=0;
		for(int i=0;i<key.length();i++){
			if(key.charAt(i)!=';'){
				dbid+=key.charAt(i);
			}else{
				index = i;
				break;
			}			
		}
		for(int i=index+1;i<key.length();i++)
			pgid += key.charAt(i);
		Page clbufpg = findPage(Integer.parseInt(dbid), Integer.parseInt(pgid));
		try{
			if(clbufpg.getBeClean()==true)
				StorageMgr.writePage(clbufpg);
		}catch(Exception e){
			System.out.println("remove: "+e.getMessage());
		}
		pageHash.remove(key);
		pageCount--;
	}
	
	//find page in buffer through dbID and pID
	public Page findPage(int dbid, int pgid){
		String key = dbid +";"+pgid;
		Page respg = pageHash.get(key);
		return respg;
	}
	//clean
	public void cleanPage(Page pg){
		
		pg.setBeClean();
		
		Page clbufpg = findPage(pg.getDataBaseID(),pg.getPageID());
		if(clbufpg!=null){
			removePage(pg.getDataBaseID()+";"+pg.getPageID());
			addPage(pg);
		}
		
		cleanList.add(pg);
		cleanCount++;

		if(cleanCount>=Global.STORAGE_CLEAN_COUNT){
			Page clpg;

			cleanCount = 0;
			for(Iterator<Page> it = cleanList.iterator(); it.hasNext();){
				clpg = it.next();
				try{
					StorageMgr.writePage(clpg);
				}catch(Exception e){
					System.out.println("Buffer: cleanPage "+e.getMessage());
				}
			}	
			cleanList.clear();
		}
	}
	
	protected void finalize( )
	{
		if(cleanCount != 0){
			System.out.println("Buffer to finalize");
			Page clpg;
			byte con[] = new byte[Global.STORAGE_PAGE_SIZE];
			for(int j=0; j<Global.STORAGE_PAGE_SIZE; j++){
				con[j] = 0x00;
			}
			cleanCount = 0;
			for(Iterator<Page> it = cleanList.iterator(); it.hasNext();){
				clpg = it.next();
				clpg.setContent(con);
				try{
					StorageMgr.writePage(clpg);
				}catch(Exception e){
					System.out.println("Buffer: cleanPage "+e.getMessage());
				}
			}	
			cleanList.clear();
		}
	}
//entry pool
}
